#ifndef THREADS_H_
#define THREADS_H_

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>

using namespace std;

/*!
 * \class Threads
 * \brief Permet d'instancier des threads.
 * 
 */
class Threads
{
	private:
		pthread_t threadEcouteNouveauClient; /*!< Thread d'ecoute de connexion de nouveau client */
		pthread_t threadTraitementNouveauClient; /*!< Thread temporaire de traitement des nouveaux clients */

		pthread_t threadLecture; /*!< Thread de lecture */

		pthread_t threadEcouteServeur; /*!< Thread d'ecoute serveur principal et de partie */
		pthread_t threadTraitementServeur; /*!< Thread d'ecoute serveur principal et de partie */
		




	public:
		Threads() {}

		/*!
		 * 
		 * Thread d'Ecoute
		 * 
		 */
		pthread_t * initEcoute()
		{
			/* Initialise les attributs du threads */
			pthread_attr_t attr;
			pthread_attr_init(&attr);
			pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);

			if( ! (pthread_create(&(this->threadEcouteNouveauClient), &attr, Threads::demarrerEcoute, static_cast<void *>(this))) )
			{
				printf("Creation du thread d'ecoute des joueurs\n");
				return &(this->threadEcouteNouveauClient);
			}
			else
			{
				printf("Echec de la creation du thread d'ecoute des joueurs\n");
				exit(0);
			}
		}
		static void * demarrerEcoute(void * thread)
		{
			static_cast<Threads *>(thread)->traitementEcoute();
			pthread_exit(NULL);
		}

		virtual void traitementEcoute() = 0;
		/*!
		 * 
		 * Thread de traitement d'un nouveau client.
		 * 
		 */
		pthread_t * traiteNouveauClient()
		{
			/* Initialise les attributs du threads */
			pthread_attr_t attr;
			pthread_attr_init(&attr);
			pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);

			if( ! (pthread_create(&(this->threadTraitementNouveauClient), &attr, Threads::traiterNouveauClient, static_cast<void *>(this))) )
			{
				printf("Creation du thread temporaire de traitement des joueurs\n");
				return &(this->threadTraitementNouveauClient);
			}
			else
			{
				printf("Echec de la creation du thread temporaire de traitement des joueurs\n");
				exit(0);
			}
		}
		static void * traiterNouveauClient(void * thread)
		{
			static_cast<Threads *>(thread)->traitementNouveauClient();
			pthread_exit(NULL);
		}
		virtual void traitementNouveauClient() = 0;








		/*!
		 * 
		 * Thread de Lecture des déplacements
		 * 
		 */
		pthread_t * initLecture()
		{	
			/* Initialise les attributs du threads */
			pthread_attr_t attr;
			pthread_attr_init(&attr);
			pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);

			if( ! (pthread_create(&(this->threadLecture), &attr, Threads::demarrerLecture, static_cast<void *>(this))) )
			{
				printf("Creation du thread Lecture des joueurs\n");
				return &(this->threadLecture);
			}
			else
			{
				printf("Echec de la creation du thread Lecture des joueurs\n");
				exit(0);
			}
		}
		
		static void * demarrerLecture(void * thread)
		{
			static_cast<Threads *>(thread)->traitementLecture();
			pthread_exit(NULL);
		}

		virtual void traitementLecture() = 0;








		/*!
		 * 
		 * Thread d'ecoute du serveur principal et de partie
		 * 
		 */		
		pthread_t * initEcouteServeur()
		{	
			/* Initialise les attributs du threads */
			pthread_attr_t attr;
			pthread_attr_init(&attr);
			pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);

			if( ! (pthread_create(&(this->threadEcouteServeur), &attr, Threads::demarrerEcouteServeur, static_cast<void *>(this))) )
			{
				printf("Creation du thread d'ecoute du serveur principal\n");
				return &(this->threadEcouteServeur);
			}
			else
			{
				printf("Echec de la creation du thread d'ecoute du serveur principal\n");
				exit(0);
			}
		}
		static void * demarrerEcouteServeur(void * thread)
		{
			static_cast<Threads *>(thread)->ecouteServeur();
			pthread_exit(NULL);
		}
		virtual void ecouteServeur() = 0;
		/*!
		 * 
		 * Thread de traitement des message du serveur principal
		 * 
		 */		
		pthread_t * initTraitementServeur()
		{	
			/* Initialise les attributs du threads */
			pthread_attr_t attr;
			pthread_attr_init(&attr);
			pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);

			if( ! (pthread_create(&(this->threadTraitementServeur), &attr, Threads::demarrerTraitementServeur, static_cast<void *>(this))) )
			{
				printf("Creation du thread de traitement du serveur principal\n");
				return &(this->threadTraitementServeur);
			}
			else
			{
				printf("Echec de la creation du thread de traitement du serveur principal\n");
				exit(0);
			}
		}
		static void * demarrerTraitementServeur(void * thread)
		{
			static_cast<Threads *>(thread)->traitementServeur();
			pthread_exit(NULL);
		}
		virtual void traitementServeur() = 0;
};
#endif /*THREADS_H_*/
